<template>
  <view class="page-container">
    <!-- 导航栏 -->
    <navbar>
      <template #leftContent>
        <image class="leftlogo" src="../../static/惠青政智答.png"></image>
      </template>
      <template #rightContent>
        <image class="rightlogo" src="../../static/清屏ico.png" @click="cleanTalk"></image>
      </template>
    </navbar>
    <!-- 问答 -->

    <!-- 提问前 -->
    <view v-if="!hasQuestion">
      <view class="welcome">
        <view class="hello">
          <view :style="{marginRight:'24rpx',height:'168rpx'}">
            <image class="assistant" src="../../static/智答助手ico.png">
            </image>
          </view>
          <view>
            <view :style="{fontSize:'30rpx', color:' #333333',fontFamily:'Source Han Sans CN',marginBottom:'28rpx'}">
              你好！我是惠青政智答助手，请问有什么可以帮你？
            </view>
            <view :style="{fontSize:'26rpx',color:'#4b5563',fontFamily:'Source Han Sans CN'}">
              我可以为你解答关于青少年教育、权益保护等方面的问题
            </view>
          </view>

        </view>
        <view class="comQuestion">
          <view :style="{color:'#333333',fontFamily:'Source Han Sans CN',fontSize:'30rpx'}">
            常见问题
          </view>
          <view class="comPolicy">
            <view v-for="(item ,index ) in welcom.policy" :key="index">
              <view class="welQuestion" @click="selectProblem(item)">
                <image src="../../static/常见问题ico.png"
                  :style="{width:'29rpx',height:'31rpx',display:'inline-block',marginRight:'24rpx'}">
                </image>
                <view :style="{display:'inline-block'}">{{item}}</view>
              </view>

            </view>
          </view>
        </view>
        <view class="news">
          <view :style="{color:'#333333',fontFamily:'Source Han Sans CN',fontSize:'30rpx'}">最新政策</view>
          <view class="newPolicy" :style="{marginTop:'16rpx'}">
            <view v-for="(item ,index) in welcom.news" :key="index">
              <view class="welPolicy" @click="selectPolicy(item)">
                <view class="newsTitle">
                  <view class="title">
                    {{item.title}}
                  </view>
                  <image src="../../static/最新政策详情ico.png" :style="{width:'12rpx',height:'21rpx'}"></image>
                </view>
                <!-- <view class="newsTime">
                  <image src="../../static/最新政策时间ico.png" :style="{width:'25rpx',height:'26rpx',marginRight:'11rpx'}"></image>
                  <view :style="{display:'inline-block'}">{{item.time}}</view>
                </view> -->
                <view class="newsDetail" v-html="item.content">

                </view>
              </view>
            </view>
          </view>
        </view>
      </view>
    </view>

    <!-- 提问后 -->
    <scroll-view v-else class="chat" scroll-y scroll-with-animation ref="chatRef" :scroll-top="scrollTop"
      :scroll-into-view="scrollIntoView">
      <!-- <view class="chat"> -->
      <view class="list">
        <!-- 显示历史消息 -->
        <view v-for="(item,index) in chatHistory" :key="index" :id="'message' + index">
          <view class="rightText">
            <view class="curQuestion">
              {{item.question}}
            </view>
          </view>
          <view class="leftTxet">
            <view class="answer">
              <view class="backGround"></view>
              <view class="answerContent">
                <view class="policy">
                  <view v-if="item.answer.policy.length">
                    <view class="count">
                      共找到{{item.answer.policy.length}}篇资料作为参考
                      <image v-if="!item.showPolicy" class="policyIcon" src="../../static/展开.png" @click="hidden(item)">
                      </image>
                      <image v-if="item.showPolicy" class="policyIcon" src="../../static/参考资料展开ico.png"
                        @click="hidden(item)"></image>
                    </view>

                    <view v-if="item.showPolicy" v-for="policies in item.answer.policy" :key="policies"
                      class="policyItem">
                      <view class="policyContent" @click="selectPolicy(policies)">{{policies.title}}</view>
                    </view>
                    <view class="policy-detail-divider"></view>
                  </view>
                </view>

                <view class="details">
                  <!-- 新增流式内容展示区域 -->
                  <view class="streaming-content">
                    <view v-if="item.isStreaming && !item.answer.content.trim()" class="thinkingTip">
                      正在思考中
                      <text class="dot">.</text>
                      <text class="dot">.</text>
                      <text class="dot">.</text>
                    </view>
                    <view v-else>
                      <ua-markdown :source="item.answer.content"></ua-markdown>
                      <!-- <text>{{item.answer.content}}</text> -->
                      <!-- 流式过程中显示光标（可选） -->
                      <text v-if="item.isStreaming" class="cursor">|</text>
                    </view>
                  </view>
                  <view class="relate" :style="{marginBottom:'24rpx'}">
                    <!-- 操作按钮-->
                    <view v-if="item.relateIcon&&index==chatHistory.length-1" class="relate"
                      :style="{marginBottom:'24rpx'}">
                      <view class="left">
                        <image src="../../static/复制btn.png" @click="handleCopy(item)"></image>
                        <image src="../../static/反馈评价btn.png" @click="handleFeedback"></image>
                        <feedback v-model:visible='showFeedback' :chatId="talkId" @submit="submitFeedback"></feedback>
                        <image src="../../static/已收藏btn.png" v-if="!nocollect" @click="collect"></image>
                        <image src="../../static/收藏btn.png" @click="collect" v-if="nocollect"></image>
                      </view>
                      <view class="right">
                        <image src="../../static/刷新btn.png" @click="refresh"></image>
                      </view>
                    </view>
                  </view>
                </view>
              </view>
            </view>
          </view>
          <view class="problem" v-if="index==chatHistory.length-1 && item.showRelated">
            <view
              :style="{fontSize:'30rpx',color:'#999999',fontFamily:'Source Han Sans CN', margin:'36rpx 0',textAlign:'center'}">
              — 您可能感兴趣 —</view>
            <view>
              <view class="relatePro" v-for="(item ,index) in problem" :key="index" @click="selectProblem(item)">
                <image src="../../static/话题ico.png"></image>
                {{item}}
              </view>
            </view>
          </view>
        </view>
      </view>
      <!-- </view> -->
    </scroll-view>
    <view class="search-container">
      <view class="input-group">
        <image class="search-icon" src="../../static/搜索ico.png"></image>
        <input class="search-input" placeholder="请输入搜索内容" v-model="question" @confirm="handleSearch"
          confirm-type="search" maxlength="50" />
        <image class="search-btn" src="../../static/发送btn.png" @click="handleSearch"></image>
      </view>
    </view>
    <view class="search-warp"></view>
  </view>

</template>

<script setup>
  import {
    ref,
    nextTick,
    onUnmounted,
    onMounted,
    computed
  } from 'vue';
  import {
    onShow
  } from '@dcloudio/uni-app';
  import {
    QAHistory
  } from '@/api/person.js';
  import loginPrompt from '@/components/loginPrompt/loginPrompt.vue';
  import navbar from '@/components/navbar/navbar';
  import createStreamRequest, {
    evaluate,
    newPolicy,
    related,
    relatedPolicy
  } from '@/api/index/output.js';
  import feedback from '@/components/feedback/feedback.vue';
  import {
    date
  } from 'uview-plus/libs/function/test';
  import code from 'uview-plus/components/u-code/code';
  import {
    login
  } from '@/api/person.js'
  // 响应式数据
  const hasQuestion = ref(false);
  const question = ref('');
  const chatHistory = ref([]);
  const scrollIntoView = ref('');
  const scrollTop = ref(0);
  const currentRequestTask = ref(null);
  const showFeedback = ref(false);
  const talkId = ref('')
  const currentQuestion = ref('')
  const chatRef = ref(null)
  const nocollect = ref(true);
  // 静态数据
  const welcom = ref({
    policy: [
      "义务教育阶段学生休学政策",
      "中考改革最新政策",
      "校园欺凌防治措施",
      "未成年人网络保护条例要点"
    ],
    news: []
  });
  //相关问题
  const problem = ref([]);
  // 左侧回答
  const answer = ref({
    policy: [],
    content: []
  })
  //用户信息
  const userInfo = ref(uni.getStorageSync('userInfo') || {
    nickName: '',
    avatarUrl: '/static/头像img.png'
  })
  const hasLogin = computed(() => !!uni.getStorageSync('token'));
  // 方法定义
  onShow(() => {
    const pages = getCurrentPages();
    const currentPage = pages[pages.length - 1];
    const {
      conversationId
    } = currentPage.options;
    if (conversationId) {
      getChat(conversationId);
    }
    getWelcomPolicy();
  })
  onMounted(async () => {
    // 等待登录完成
    const loginSuccess = await silentLogin();
    if (loginSuccess) {
      // 登录成功后再获取政策数据
      getWelcomPolicy();
    } else {
      // 登录失败处理
      uni.showToast({
        title: '登录失败，部分功能受限',
        icon: 'none'
      });
    }
  });
  const getChat = (id) => {
    QAHistory({
      conversationId: id
    }).then((res) => {
      if (res.code === 200) {
        talkId.value = res.conversationId;
        hasQuestion.value = true;
        console.log(hasQuestion.value)
        // 假设聊天记录数组在 res.rows（根据实际接口调整）
        chatHistory.value = res.rows.map(chat => ({
          question: chat.usercontent,
          answer: {
            policy: '',
            content: chat.syscontent
          },
          isStreaming: false,
          relateIcon: false, // 刷新等按钮的显示
          showPolicy: false, // 显示相关政策属性
          showRelated: false, // 显示相关问题属性
        }));
        // 假设 conversationId 在 res 根层级（根据实际接口调整）

      }
    });
  };
  const silentLogin = () => {
    return new Promise((resolve, reject) => {
      const token = uni.getStorageSync('token');

      // 如果有token且未过期，直接resolve
      if (token) {
        console.log('已存在有效token', token);
        resolve(true); // 表示已登录
        return;
      }

      // 执行微信登录流程
      uni.login({
        provider: 'weixin',
        success: (loginRes) => {
          // 测试用固定code，实际应该使用loginRes.code
          loginRes.code = "1111";

          login(loginRes.code).then((res) => {
            if (res.code === 200 && res.token) {
              uni.setStorageSync('token', res.token);
              console.log('登录成功，获取新token', res.token);
              resolve(true); // 登录成功
            } else {
              console.error('登录接口返回异常', res);
              resolve(false); // 登录失败
            }
          })
        }
      });
    });
  }
  //获得最新政策
  const getWelcomPolicy = () => {
    newPolicy().then((res) => {
      if (res.code === 200) {
        welcom.value.news = res.data.map(item => ({
          id: item.policyId,
          content: item.content,
          title: item.title
        }))
      }
    })
  }
  // 滚动到底部函数
  const scrollToBottom = (immediate = false) => {
    nextTick(() => {
      const query = uni.createSelectorQuery();
      query.select('.chat').boundingClientRect();
      query.select('.list').boundingClientRect();
      query.exec((res) => {
        const scollViewHeight = res[0].height
        const scrollContentHeight = res[1].height
        if (scrollContentHeight > scollViewHeight) {
          scrollTop.value = scrollContentHeight - scollViewHeight + 50
        }
      });

    });
  }
  //点击是否显示政策
  const hidden = (item) => {
    item.showPolicy = !item.showPolicy
  }
  const selectPolicy = (policy) => {
    uni.navigateTo({
      // url: `/pages/index/policy?id=${policy.id}`
      url: `/pages/newPolicy/newPolicy?id=${policy.id}`
    })
  }
  //停止当前回答，关闭流式输出
  const abortCurrentRequest = () => {
    if (currentRequestTask.value) {
      currentRequestTask.value.abort();
      currentRequestTask.value = null;
    }
  };
  //注销监听事件
  const cleanupListeners = (messageHandler) => {
    uni.$off('stream-message', messageHandler);
    uni.$off('stream-end', messageHandler);
    uni.$off('stream-error', messageHandler);
  };
  //封装流式输出
  const stream = (newMessageIndex) => {
    //监听所得event进行流式输出
    const messageHandler = (event) => {
      const {
        type,
        data
      } = event;
      if (type === 'message') {
        handleStreamMessage(data, newMessageIndex);
      } else if (type === 'stream_end') {
        handleStreamDone(newMessageIndex);
        cleanupListeners(messageHandler);
      } else if (type === 'stream_error') {
        handleStreamError(event.error, newMessageIndex);
        cleanupListeners(messageHandler);
      }
    };
    //得到当前对话Id
    const getTalkId = (event) => {
      const {
        conversation_id,
      } = event;
      talkId.value = conversation_id;
    }
    // 注册事件监听
    uni.$on('stream-continue', getTalkId)
    uni.$on('stream-message', messageHandler);
    uni.$on('stream-end', messageHandler);
    uni.$on('stream-error', messageHandler);

    // 发起流式请求
    currentRequestTask.value = createStreamRequest(currentQuestion.value, talkId.value);
  }
  //点击提交搜索问题
  const handleSearch = () => {
    console.log(talkId.value);
    if (!question.value.trim()) return;
    currentQuestion.value = question.value;
    const newMessageIndex = chatHistory.value.length;
    // 添加新消息到历史记录
    chatHistory.value.push({
      question: currentQuestion.value,
      answer: {
        policy: '',
        content: ''
      },
      isStreaming: true,
      //刷新等按钮的显示
      relateIcon: false,
      //显示相关政策属性
      showPolicy: false,
      //显示相关问题属性
      showRelated: false,

    });
    question.value = '';
    hasQuestion.value = true;
    getPolicy();
    //自动滚动
    scrollToBottom();
    //调用流式输出
    stream(newMessageIndex);
    //得到相关问题
    getRelatedQuestion();
  };
  //获取流式输出内容
  const handleStreamMessage = (data, messageIndex) => {
    if (messageIndex < chatHistory.value.length) {
      const message = chatHistory.value[messageIndex];
      if (data.text) {
        message.answer.content =
          (message.answer.content || '') + data.text;
      }
      // 触发视图更新
      chatHistory.value = [...chatHistory.value];
      scrollToBottom()
    }
  }
  //流式输出结束
  const handleStreamDone = (messageIndex) => {
    if (messageIndex < chatHistory.value.length) {
      chatHistory.value[messageIndex].isStreaming = false;
      chatHistory.value[messageIndex].relateIcon = true;
      chatHistory.value[messageIndex].showRelated = true;
      chatHistory.value = [...chatHistory.value];
      scrollToBottom()
    }
    currentRequestTask.value = null;
  };


  //流式输出出错
  const handleStreamError = (error, messageIndex) => {
    if (messageIndex < chatHistory.value.length) {
      const message = chatHistory.value[messageIndex];
      message.isStreaming = false;
      message.relateIcon = true;
      message.showRelated = true;
      message.error = error;
      chatHistory.value = [...chatHistory.value];
      uni.showToast({
        title: '请求失败，请重试',
        icon: 'error',
        duration: 2000
      });
    }
    currentRequestTask.value = null;
  };
  const getPolicy = () => {
    const chatLength = chatHistory.value.length;
    if (chatLength === 0) return
    const question = currentQuestion.value;
    const currentChat = chatHistory.value[chatLength - 1];
    relatedPolicy(question).then((res) => {
      if (res.code === 200) {
        currentChat.answer.policy = res.data.map(item => ({
          id: item.policyId,
          title: item.title
        }));
        chatHistory.value = [...chatHistory.value];
      };
    });
  }
  //得到相关问题
  const getRelatedQuestion = () => {
    let text = '';
    const chatLength = chatHistory.value.length;
    const startIndex = Math.max(0, chatLength - 5);
    const recentQuestions = chatHistory.value.slice(startIndex).map(item => item.question);
    const questionText = recentQuestions.join('; ');
    console.log(questionText);
    related(questionText).then((res) => {
      if (res.code == 200) {
        problem.value = res.data.map(item => item.question.replace(/"/g, '').trim());
      }
    })
  }
  //点击选择某个相关问题
  const selectProblem = (item) => {
    question.value = item;
    handleSearch();
  };
  //复制回答
  const handleCopy = (item) => {
    let copyText = '';
    if (item.answer.content.trim()) {
      copyText += `${item.answer.content}\n\n`;
    }
    uni.setClipboardData({
      data: copyText,
      success: () => {
        uni.showToast({
          title: "复制成功",
          icon: 'success',
          duration: 1000
        });

      },
    });
  };
  //点击显示反馈弹窗
  const handleFeedback = () => {
    showFeedback.value = true;
  };
  //提交反馈内容
  const submitFeedback = (data) => {
    evaluate(data).then((res) => {
      if (res.code === 200) {
        uni.showToast({
          title: '感谢您的反馈',
          icon: 'success'
        });
      }
    })
  };
  //停止当前回答
  onUnmounted(() => {
    abortCurrentRequest();
  });
  //清屏按钮点击事件
  const cleanTalk = () => {
    talkId.value = '',
      hasQuestion.value = false,
      chatHistory.value = []
  }
  //刷新按钮点击事件，重新回答
  const refresh = () => {
    const chatLength = chatHistory.value.length;
    if (chatLength > 0) {
      const lastMessage = chatHistory.value[chatLength - 1];
      //将之前的回答清除
      currentQuestion.value = lastMessage.question;
      lastMessage.answer.content = '';
      lastMessage.answer.policy = '';
      lastMessage.showPolicy = false;
      lastMessage.showRelated = false;
      problem.value = [];
      lastMessage.isStreaming = true;
      //如果正在进行回答，那么中止回答
      if (currentRequestTask.value) {
        abortCurrentRequest();
        currentRequestTask.value = null;
      }
      
      //调用流式输出方法
      stream(chatLength - 1);
      getRelatedQuestion();
      getPolicy();
      scrollToBottom()
    }
  }
  //点击收藏按钮
  const collect = () => {
    const data = ref({});
    data.value.isFavorite = nocollect.value ? 0 : 1;
    data.value.conversationId = talkId.value;
    evaluate(data.value).then((res => {
      if (res.code === 200) {
        nocollect.value = !nocollect.value;
      }
    }))
  }
</script>

<style>
  .page-container {
    position: relative;
    height: 100vh;
    display: flex;
    flex-direction: column;
  }

  .navbar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 100;
  }

  .pop-warp {
    position: fixed;
    min-width: 500rpx;
    background: #fff;
    min-height: 200rpx;
    padding: 32rpx;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    border-radius: 20rpx;
  }

  .welcome {
    padding: 0 30rpx;
    background-image: url("../../static/对话背景ico.png");
    background-repeat: no-repeat;
    background-size: cover;
    box-sizing: border-box;
  }

  .hello {
    background-color: #fef2f2;
    border: 2rpx solid #f9d5d4;
    border-radius: 16rpx;
    width: calc(690rpx);
    height: calc(248rpx);
    margin-top: 30rpx;
    box-sizing: border-box;
    padding: 30rpx 40rpx;
    display: flex;
    align-items: center;
  }

  .assistant {
    width: 56rpx;
    height: 76rpx;

  }

  .comQuestion {
    margin-top: 48rpx;
    margin-bottom: 48rpx;
  }


  .welQuestion {
    background-color: #ffffff;
    border: 2rpx solid #eeeeee;
    border-radius: 16rpx;
    height: 102rpx;
    display: flex;
    align-items: center;
    margin-top: 24rpx;
    padding-left: 30rpx;
    padding-right: 30rpx;
  }

  .news {
    padding-bottom: 160rpx;
  }

  .welPolicy {
    display: flex;
    flex-direction: column;
    padding: 0 30rpx;
    background-color: #ffffff;
    border: 2rpx solid #eeeeee;
    border-radius: 16rpx;
    height: 250rpx;
    margin: 8rpx 0;
    width: 690rpx;
    box-sizing: border-box;
  }

  .newsTitle {
    margin-top: 40rpx;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .newsTitle .title {
    flex: 1;
    margin-right: 11rpx;
    width: 600rpx;
    font-size: 30rpx;
    color: #333333;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .newsTime {
    font-size: 26rpx;
    color: #9ca3af;
    margin: 24rpx 0;
  }

  .newsDetail {
    margin-top: 30rpx;
    display: -webkit-box !important;
    font-size: 28rpx;
    color: #4b5563;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
    -webkit-box-orient: vertical !important;
  }

  .chat {
    flex: 1;
    padding: 0 30rpx 130rpx;
    box-sizing: border-box;
    display: flex;
    -webkit-overflow-scrolling: touch;
    overflow-y: auto;
    height: (100vh - 130rpx);
  }

  .list {
    display: flex;
    flex-direction: column;
    min-height: min-content;
  }

  .chat .rightText {
    direction: ltr;
    max-width: 70%;
    margin-left: auto;
    box-sizing: border-box;
    display: flex;
    justify-content: flex-end;
    text-align: right;
  }

  .curQuestion {
    background-color: #e1383c;
    margin-top: 50rpx;
    color: white;
    border-radius: 16rpx 0 16rpx 16rpx;
    display: inline-block;
    padding: 24rpx;
    font-size: 32rpx;
    margin-bottom: 50rpx;
    word-break: break-word;
    white-space: pre-wrap;
    text-align: left;
  }

  .answer {
    position: relative;
    overflow-y: auto;
    flex: 1;
    min-height: 200rpx;
    /* background-image: url("../../static/对话背景ico.png"); */
  }

  .leftTxet {
    background-color: #f5f5f5;
    white-space: pre-line;
    border-radius: 0 16rpx 16rpx 16rpx;
    padding: 0 24rpx;
    box-sizing: border-box;
    margin-bottom: 36rpx;
  }

  .detailTitle {
    margin: 15rpx 0;
    font-size: 32rpx;
    color: #333333;

  }

  .detailContent {
    margin: 15rpx 36rpx;
    font-size: 28rpx;
    color: #4b5563;
  }

  .count {
    margin-top: 36rpx;
    margin-bottom: 36rpx;
    color: #9ca3af;
    font-size: 30rpx;
    display: block;
    position: relative;
  }

  .policyItem {
    position: relative;
    margin-bottom: 15rpx;
    color: #0066ff;
    font-size: 30rpx;
  }

  .policyContent {
    display: -webkit-box !important;
    overflow: hidden;
    text-overflow: ellipsis;
    word-break: break-all;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical !important;
  }

  .policy .policyIcon {
    width: 21rpx;
    height: 12rpx;
    margin-left: 12rpx;
  }

  .policy-detail-divider {
    height: 1rpx;
    /* 分隔符高度 */
    margin: 15rpx 0;
    /* 上下边距控制与内容的间距 */
    border-top: 2rpx dashed #9ca3af;
    /* 虚线样式：1rpx宽，灰色 */
  }

  .relate image {
    height: 56rpx;
    width: 56rpx;
    margin-right: 12rpx;

  }

  .relate .left {
    display: inline-block;
    margin-right: 370rpx;
  }

  .relate .right {
    display: inline-block;
  }

  .relatePro {
    min-height: 80rpx;
    padding: 24rpx;
    box-sizing: border-box;
    border: 2rpx solid #eeeeee;
    border-radius: 16rpx;
    margin-bottom: 16rpx;
    display: inline-block;
    font-size: 28rpx;
    max-width: 620rpx;
  }

  .relatePro image {
    width: 19rpx;
    height: 23rpx;
  }

  .search-container {
    position: fixed;
    bottom: 30rpx;
    left: 30rpx;
    right: 30rpx;
    z-index: 5;
    display: flex;
    align-items: center;
    background: #fff;
    border-radius: 40rpx;
    height: 98rpx;
    width: 690rpx;
    box-shadow: 0 2rpx 16rpx #f5f5f5;
  }

  .search-warp {
    height: 130rpx;
    background: #ffffff;
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
  }

  .input-group {
    display: flex;
    align-items: center;
    width: 100%;
    padding: 0 30rpx;
  }

  .search-icon {
    width: 28rpx;
    height: 28rpx;
    margin-right: 12rpx;
  }

  .search-input {
    flex: 1;
    height: 30rpx;
    font-size: 30rpx;
  }

  .search-btn {
    width: 40rpx;
    height: 40rpx;
    margin-left: 20rpx;
  }

  .leftlogo {
    height: 48rpx;
    width: 200rpx;
  }

  .rightlogo {
    height: 56rpx;
    width: 56rpx;
  }

  .streaming-content {
    margin: 15rpx 0;
    white-space: pre-wrap;
  }

  .thinkingTip {
    color: #9ca3af;
    font-size: 28rpx;
  }

  .dot {
    opacity: 0;
    animation: dot-animation 1.5s infinite;
  }

  .dot:nth-child(2) {
    animation-delay: 0.2s;
  }

  .dot:nth-child(3) {
    animation-delay: 0.4s;
  }

  @keyframes dot-animation {

    0%,
    100% {
      opacity: 0;
    }

    50% {
      opacity: 1;
    }
  }

  .cursor {
    animation: blink 1s step-end infinite;
  }

  @keyframes blink {
    50% {
      opacity: 0;
    }
  }

  /* 登录弹窗样式 */
  .login-popup {
    padding: 40rpx;
    text-align: center;
  }

  .login-popup .title {
    font-size: 32rpx;
    margin-bottom: 40rpx;
  }

  .login-popup .avatar-btn {
    background: none;
    padding-top: 25rpx;
    margin-bottom: 30rpx;
  }

  .login-popup .avatar-btn .avatar {
    width: 120rpx;
    height: 120rpx;
    border-radius: 25%;
  }

  .login-popup .nickname-input {
    display: flex;
    align-items: center;
    margin: 30rpx 0;
    padding: 0 20rpx;
  }

  .login-popup .nickname-input input {
    flex: 1;
    height: 60rpx;
    border: 1rpx solid #eee;
    border-radius: 10rpx;
    padding: 0 20rpx;
  }

  .login-popup .confirm-btn {
    background: #007aff;
    color: white;
    height: 80rpx;
    line-height: 80rpx;
    border-radius: 40rpx;
    margin-top: 40rpx;
  }
</style>